#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER
	
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>"||ls.getSymCour()=="si"||ls.getSymCour()=="tantque"||ls.getSymCour()=="pour"||
                        ls.getSymCour()=="repeter"||ls.getSymCour()=="ecrire"||ls.getSymCour()=="lire");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst() {
// <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>

    if(ls.getSymCour()=="si")
	instSi();
    else if(ls.getSymCour()=="tantque")
 	instTq();
    else if(ls.getSymCour()=="repeter")
   	instRepeter();
    else if(ls.getSymCour()=="pour")
   	instPour();   
    else if(ls.getSymCour()=="ecrire")
   	instEcrire();
    else if(ls.getSymCour()=="lire")
   	instLire();   
    else
    	affectation();
       
   
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>

	sauterSymCour("<VARIABLE>");
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-" ) {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
//  <facteur> ::= <entier> | <variable> | <opUnaire> <expBool> | ( <expBool> ) 


	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();
	else if (ls.getSymCour()=="-"|| ls.getSymCour()=="non") {
		opUnaire();
		expBool();
        }
        else if (ls.getSymCour()=="(") {
		ls.suivant();
		expBool();
		sauterSymCour(")");
	} 
        else
		erreur("<facteur>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opAdd()
// <opAdd>  ::= + | - 
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-") 
		
		ls.suivant();
	else
		erreur("<opAdd>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme()
    // <terme> ::= <facteur> { <opMult> facteur> }
{
    facteur();
    while(ls.getSymCour()=="*" || ls.getSymCour()=="/"){
        opMult();
        facteur();
    }
    
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
//<opMult>  ::= * | /
{
	if ( ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opMult>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expBool(){
//  <expBool> ::= <Bool> { <opOu> <Bool> } 

	Bool();
	while (ls.getSymCour()=="et" || ls.getSymCour()=="ou")
                 {
		opOu();
		Bool();
                }
        
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::Bool(){
//  <Bool> ::= <relation> { <opEt> <relation>}

    relation();
    	while (ls.getSymCour()=="et")
                 {
		opEt();
		relation();
                }
        
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opOu()
//   <opOu> ::= ou
{
	if (ls.getSymCour()=="ou") 
		
		ls.suivant();
	else
		erreur("<opBool>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opEt()
// <opEt> ::= et
{
	if (ls.getSymCour()=="et") 
		
		ls.suivant();
	else
		erreur("<opBool>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::relation()
//  <relation> ::= <expression> { <opRel> <expression> }
{

	expression();
	while(ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<"|| 
            ls.getSymCour()=="<="|| ls.getSymCour()==">"|| ls.getSymCour()==">=")
                 {
		opRel();
		expression();
                }
	
 
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opRel()
//  <opRel> ::= == | != | < | <= | > | >=
{
	if (ls.getSymCour()=="==" || ls.getSymCour()==":=" || ls.getSymCour()=="<"|| 
            ls.getSymCour()=="<="|| ls.getSymCour()==">"|| ls.getSymCour()==">=") 
		
		ls.suivant();
	else
		erreur("<opRel>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opUnaire()
//  <opUnaire> ::= - | non 
{
	if (ls.getSymCour()=="-" || ls.getSymCour()=="non") 
		
		ls.suivant();
	else
		erreur("<opUnaire>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instSi()
//  <instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> }[ sinon <seqInst> ] finsi
{
    
   sauterSymCour("si");
   sauterSymCour("(");
   expBool();
   sauterSymCour(")");
   seqInst();
                
       while(ls.getSymCour()=="sinonsi")
       {
             
           sauterSymCour("sinonsi");
           sauterSymCour("(");
           expBool();
           sauterSymCour(")");
           seqInst();
                               
       }
   if(ls.getSymCour()=="sinon"){
       sauterSymCour("sinon");
       seqInst();
   }
    sauterSymCour("finsi");


}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instTq()
//  <instTq> ::= tantque ( <expBool> ) <seqInst> fintantque 
{
   sauterSymCour("tantque");
   sauterSymCour("(");
   expBool();
   sauterSymCour(")");
   seqInst();
   sauterSymCour("fintantque");
          
        
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instPour()
//  <instPour> ::= pour ( <affectation> ; <expBool> ; <affectation> ) <seqInst> finpour
{
   sauterSymCour("pour");
   sauterSymCour("(");
   affectation();
   sauterSymCour(";");
   expBool();
   sauterSymCour(";");
   affectation();
   sauterSymCour(")");
   seqInst();
   sauterSymCour("finpour");
          
        
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instRepeter()
//  <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
{
   sauterSymCour("repeter");
   seqInst();
   sauterSymCour("jusqua");
   sauterSymCour("(");
   expBool();
   sauterSymCour(")");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instLire()
//  <instLire> ::= lire ( <variable> )
{
   sauterSymCour("lire");
   sauterSymCour("(");
        if(ls.getSymCour()=="<VARIABLE>"){
            ls.suivant();
        }
        else{erreur("<instLire>");}
   sauterSymCour(")");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instEcrire()
//  <instEcrire> ::= ecrire ( <expression> | <chaine> )
{
   sauterSymCour("ecrire");
   sauterSymCour("(");
        if(ls.getSymCour()=="<CHAINE>"){
            ls.suivant();
        }
        else{expression();}
   sauterSymCour(")");
   
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}







